package com.atguigu.listener;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.util.Map;

@Configuration
public class RabbitmqListener {
//    @RabbitListener  标注的一个方法就是mq的一个消费者
    /*
        springboot mq消费者默认消息确认方式：
            1、auto
                消息消费成功自动ack，如果有异常消费失败不会ack无限重试确认消费消息
                如果消费异常的消费者停止 消息又变成可以消费的状态
            2、none

     */
    @RabbitListener(queues = { //消费已存在的队列 中的消息
            "test1.queue"
    })
    public void test1Listener(Message message , String msg , Channel channel) throws IOException {
        try {
            System.out.println(msg);
            int i = 1/0;
            //手动确认消息   参数2：不批量确认消息的消费
            channel.basicAck(message.getMessageProperties().getDeliveryTag()
                    ,false);
        } catch (Exception e) {
            e.printStackTrace();
            if(message.getMessageProperties().isRedelivered()){
                //如果消息重复消费后仍消费失败  丢弃消息
                //如果没有绑定死信队列 消息直接丢弃，如果绑定了死信队列 消息会被丢弃到死信队列
                channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);
            }else{
                //业务执行有异常 消息没能正常消费
                //第一次消费出现异常可以拒绝确认消息的消费:让消息重新归队
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),false , true);
            }


        }
    }
    //通过注解创建交换机队列 绑定
    @RabbitListener(bindings = {
            @QueueBinding(
                    exchange = @Exchange(
                           name = "test2.exchange", //交换机名
                            durable = "true", //持久化
                            type = ExchangeTypes.TOPIC, //类型
                            ignoreDeclarationExceptions = "true" //异常忽略
                    ),
                    value = @Queue(
                            name = "test2.queue",
                            durable = "true"
                    ),
                    key = "test2.#"  //路由key
            )
    })
    public void test2Listener(Message message , String msg , Channel channel){
        try {
            System.out.println("接收到消息: "+msg);
            System.out.println(new String(message.getBody()));
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @RabbitListener(queues = {
            "test3.queue"
    })
    public void test3Listener(Message message , Map map , Channel channel) throws IOException {

        try {
            System.out.println(map);
            int i = 2/0;
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            e.printStackTrace();
            if(message.getMessageProperties().isRedelivered()){
                channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);
            }else{
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                        false,true);
            }

        }
    }


}
